package com.inspur.gs.sbssdl.sbwhgl.sbrh.sbrh.back.luCreatFactory;

import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.bef.core.LcpUtil;
import com.inspur.edp.bef.engine.entity.AssociationInfo;
import com.inspur.edp.cef.entity.changeset.ModifyChangeDetail;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.condition.FilterCondition;
import com.inspur.edp.cef.entity.condition.FilterConditionBuilder;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IValuesContainer;
import com.inspur.edp.qdp.bql.api.IBqlExecuter;
import com.inspur.edp.qdp.bql.api.OptionType;
import io.iec.edp.caf.runtime.config.BqlBeanUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class LuCreat {
    private final List<String> devIds;
    private final String tzCfg = "com.inspur.gs.sbssdl.sbssgl.sbtz.sbtz.back.SbssSbtz";
    private final String rhmxCfg = "com.inspur.gs.sbssdl.sbssgl.sbtz.sbtz.back.sbssSbrhMx";
    private final LuTimeUtil timeUtil = new LuTimeUtil();
    private final IBqlExecuter bqlExecuter = BqlBeanUtil.getAppCtx().getBean(IBqlExecuter.class);
    private final String rhrwCfg = "com.inspur.gs.sbssdl.sbwhgl.sbrh.sbrh.back.sbssSbrhRw";
    private final String byjh = "com.inspur.gs.sbssdl.sbwhgl.sbwhby.sbwhby.back.newsbdjjh";

    public LuCreat(List<String> devIds) {
        this.devIds = devIds;
    }

    @Getter
    @Setter
    public boolean scheduler = false;

    public void creatLu() {
        IStandardLcp tzLcp = LcpUtil.getLcp(tzCfg);
        IStandardLcp rhmxLcp = LcpUtil.getLcp(rhmxCfg);
        IStandardLcp taskLcp = LcpUtil.getLcp(rhrwCfg);
        IStandardLcp byLcp = LcpUtil.getLcp(byjh);
        bqlExecuter.getOptions().setOptionType(OptionType.ExecuteSql);
        String bizDefKey = "e2eed625-a68b-45ab-912d-a76e5f269768";

        devIds.parallelStream()
                .forEach(devId -> {
                    // 查询实体
                    IEntityData devEntity = getEntityData(tzLcp, devId);
                    if (devEntity == null) {
                        return;
                    }

                    // 获取标准
                    List<IEntityData> lustand = getMxData(rhmxLcp, devId);

                    // 检查并过滤已生成的标准
                    List<HashMap<String, Object>> data = lustand.stream()
                            // 筛选周期性的标准
                            .filter(i->filterBY(tzLcp,byLcp,i,devId))
                            .map(this::tranToMap)
                            .filter(i -> checkIsCreated(devId, i))
                            .collect(Collectors.toList());

                    // 创建任务
                    if (data.isEmpty()) {
                        return;
                    }
                    HashMap<String, String> devMap = IEntityDataToMap(devEntity);
                    // SQL创建
                    String taskId = creatTaskScheduler(devMap, data);

                    // 提交审批
                    TaskFlowCreater.getTaskFlow(taskId, bizDefKey);
                });
    }


    /**
     * 查询主表
     *
     * @param devLcp
     * @param devId
     * @return
     */
    private IEntityData getEntityData(IStandardLcp devLcp, String devId) {
        EntityFilter filter = new EntityFilter();
        // 开启润滑并已配置润滑项目
        ArrayList<FilterCondition> filters = new ArrayList<>(
                FilterCondition.builder()
                        .andEqual("id", devId)
                        .andEqual("rh", "true")
                        .andEqual("rhp", "true")
                        .andEqual("zt","9a453168-96d9-4389-9654-a7930a7f4481")
                        .build()
        );
        filter.setFilterConditions(filters);
        List<IEntityData> query = devLcp.query(filter);
        if (!query.isEmpty()) {
            return query.get(0);
        }
        return null;
    }

    /**
     * 查询明细表
     *
     * @param mxLcp
     * @param parentId
     * @return
     */
    private List<IEntityData> getMxData(IStandardLcp mxLcp, String parentId) {
        EntityFilter filter = new EntityFilter();
        // 已开启的润滑项目
        ArrayList<FilterCondition> filters = new ArrayList<>(
                FilterCondition.builder()
                        .andEqual("parentid", parentId)
                        .andEqual("lustand_luActive", "true")
                        .build()
        );
        filter.setFilterConditions(filters);
        List<IEntityData> query = mxLcp.query(filter);
        if (query.isEmpty()) {
            return new ArrayList<>();
        }
        return query;
    }

    /**
     * 一级过滤类型为保养以及台时的标准
     *
     * @param lu
     * @return
     */
    private boolean filterBY(IStandardLcp tzLcp,IStandardLcp byLcp,IEntityData lu,String devId) {
        AssociationInfo luStandInfo = (AssociationInfo) lu.getValue("lustand");

        String cycleLabel = luStandInfo.getValue("lustand_cycleLabel").toString();
        String cycleType = luStandInfo.getValue("lustand_cycleType").toString();

        // 定时器调用只执行周期性的任务
        if (scheduler){
            return cycleType.equals("1") && Integer.parseInt(cycleLabel) <= 6;
        }else {
            // 如果被外部调用,则生成随保养的任务
            if (cycleType.equals("1") && Integer.parseInt(cycleLabel) <= 6){
                return true;
            }else if (Integer.parseInt(cycleLabel) == 7){
                return checkBaoYang(tzLcp,byLcp,devId,"1");
            }else if (Integer.parseInt(cycleLabel) == 8){
                return checkBaoYang(tzLcp,byLcp,devId,"2");
            }else {
                return false;
            }
        }


    }

    /**
     * 数据转换成map
     *
     * @param lu
     * @return
     */
    private HashMap<String, Object> tranToMap(IEntityData lu) {
        HashMap<String, Object> data = new HashMap<>();

        AssociationInfo luStandInfo = (AssociationInfo) lu.getValue("lustand");
        String devClass = getString(luStandInfo.getValue("lustand_devClass"));
        String devSpec = getString(luStandInfo.getValue("lustand_devSpec"));
        String luMech = getString(luStandInfo.getValue("lustand_luMech"));
        String luItem = getString(luStandInfo.getValue("lustand_luItem"));
        String luFatName = getString(luStandInfo.getValue("lustand_luFatName"));
        String luMode = getString(luStandInfo.getValue("lustand_luMode"));
        String note = getString(luStandInfo.getValue("lustand_note"));
        String cycleType = getString(luStandInfo.getValue("lustand_cycleType"));
        String cycleLabel = getString(luStandInfo.getValue("lustand_cycleLabel"));
        int cycleValue = (Integer) luStandInfo.getValue("lustand_cycleValue");

        data.put("luStandId", getString(luStandInfo.getValue("lustand")));
        data.put("devClass", devClass);
        data.put("devSpec", devSpec);
        data.put("luMech", luMech);
        data.put("luItem", luItem);
        data.put("luFatName", luFatName);
        data.put("luMode", luMode);
        data.put("cycleType", cycleType);
        data.put("cycleLabel", cycleLabel);
        data.put("cycleValue", cycleValue);
        data.put("note", note);

        if (Integer.parseInt(cycleLabel) <= 6) {
            List<String> startAndEndTimer = timeUtil.getStartAndEndTimer(cycleLabel, cycleValue);
            if (startAndEndTimer == null || startAndEndTimer.size() != 2) {
                log.error("{}:{}的{}标准润滑任务 开始时间或结束时间异常! 请检查!", luStandInfo.getValue("lustand").toString(), cycleLabel, cycleValue);
            } else {
                data.put("startTime", startAndEndTimer.get(0));
                data.put("endTime", startAndEndTimer.get(1));
            }
            return data;
        } else {
            // 当月
            List<String> startAndEndTimer = timeUtil.getStartAndEndTimer("4", 1);
            data.put("startTime", startAndEndTimer.get(0));
            data.put("endTime", startAndEndTimer.get(1));
            return data;
        }
    }

    /**
     * 查询标准润滑配置
     *
     * @param devId
     * @param byType 1 一保 2 二保
     * @return 有没有保养计划, 有保养计划返回true, 否则返回false
     */
    private boolean checkBaoYang(IStandardLcp tzLcp,IStandardLcp byLcp,String devId, String byType) {
        int monthValue = LocalDateTime.now().getMonthValue();

        // 检查是否开启一保/二保
        EntityFilter filter = new EntityFilter();
        FilterConditionBuilder builder = FilterCondition.builder()
                .andEqual("id", devId);
        if (byType.equals("1")) {
            builder.andEqual("ry","true");
        }else {
            builder.andEqual("re","true");
        }
        ArrayList<FilterCondition> filters = new ArrayList<>(builder.build());
        filter.setFilterConditions(filters);
        List<IEntityData> query = tzLcp.query(filter);
        if (query.isEmpty()) {
            return false;
        }
        IEntityData dev = query.get(0);

        filter = new EntityFilter();
        // 是否属于当月保养
        filters = new ArrayList<>(
                FilterCondition.builder()
                        .andEqual("SBBH", dev.getValue("sbbh").toString())
                        .andEqual("month" + monthValue, byType)
                        .build()
        );
        filter.setFilterConditions(filters);
        query = byLcp.query(filter);

        return !query.isEmpty();
    }

    /**
     * 二级过滤已产生任务计划的标准
     *
     * @param devId
     * @param lu
     * @return
     */
    private boolean checkIsCreated(String devId, HashMap<String, Object> lu) {
        String luStandId = lu.get("luStandId").toString();

        if (!lu.containsKey("startTime") && !lu.containsKey("endTime")) {
            log.error("{}的{}标准润滑任务没有开始时间或结束时间! 请检查!", devId, luStandId);
            return false;
        }

        String startTime = lu.get("startTime").toString();
        // String endTime = lu.get("endTime").toString();

        // 开始时间是否在范围内
        String sql = " select mx.id from SBSS_SBRH_TASK task join SBSS_SBRH_TASKMX mx on mx.parentId = task.id " +
                " WHERE task.BILLSTATUS != '3' " +
                " AND task.sbid = '" + devId + "' " +
                " AND mx.luStandId = '" + luStandId + "' " +
                " AND (mx.STARTTIME <= to_date('" + startTime + "','YYYY-MM-DD HH24:MI:SS') " +
                " and mx.ENDTIME > to_date('" + startTime + "','YYYY-MM-DD HH24:MI:SS')) ";
        return bqlExecuter.executeSelectStatement(sql, new ArrayList<>()).isEmpty();
    }

    /**
     * 创建任务主子表
     *
     * @param data
     * @return
     */
    @Deprecated
    private ModifyChangeDetail creatTask(IStandardLcp taskLcp, HashMap<String, String> devMap, List<HashMap<String, Object>> data) {
        // 创建数据
        IEntityData iEntityData = taskLcp.retrieveDefault();
        ModifyChangeDetail modify = new ModifyChangeDetail(iEntityData.getID());

        modify.setItem("TaskName", devMap.get("sbmc") + "的润滑计划");
        modify.setItem("sbid", devMap.get("sbid"));
        modify.setItem("sbbh", devMap.get("sbbh"));
        modify.setItem("sbbh_old", devMap.get("sbbh_old"));
        modify.setItem("sbmc", devMap.get("sbmc"));
        modify.setItem("sbld_lbbh", devMap.get("sbld_lbbh"));
        modify.setItem("sbld_lbmc", devMap.get("sbld_lbmc"));
        modify.setItem("bm_id", devMap.get("bm_id"));
        modify.setItem("bm_bh", devMap.get("bm_bh"));
        modify.setItem("bm_mc", devMap.get("bm_mc"));
        modify.setItem("shop_id", devMap.get("shop_id"));
        modify.setItem("shop_code", devMap.get("shop_code"));
        modify.setItem("shop_name", devMap.get("shop_name"));
        modify.setItem("zt_id", devMap.get("zt_id"));
        modify.setItem("zt_ztmc", devMap.get("zt_ztmc"));
        modify.setItem("abc_id", devMap.get("abc_id"));
        modify.setItem("abc_mc", devMap.get("abc_mc"));
        modify.setItem("ggxh", devMap.get("ggxh"));
        modify.setItem("xh", devMap.get("xh"));

        DateTimeFormatter dateTimeFormatter = timeUtil.getDateTimeFormatter();

        for (HashMap<String, Object> d : data) {
            ArrayList<String> nodeCodes = new ArrayList<>();
            nodeCodes.add("RwMx");
            ArrayList<String> hierarchyIds = new ArrayList<>();
            hierarchyIds.add(iEntityData.getID());

            IEntityData mxData = taskLcp.retrieveDefaultChild(nodeCodes, hierarchyIds);
            ModifyChangeDetail mxModify = new ModifyChangeDetail(mxData.getID());

            String startTimeStr = d.get("startTime").toString();
            String endTimeStr = d.get("endTime").toString();
            LocalDateTime srtTime = LocalDateTime.parse(startTimeStr, dateTimeFormatter);
            LocalDateTime edTime = LocalDateTime.parse(endTimeStr, dateTimeFormatter);
            Instant srtInstant = srtTime.toInstant(ZoneOffset.ofHours(8));
            Instant edInstant = edTime.toInstant(ZoneOffset.ofHours(8));
            mxModify.setItem("startTime", Date.from(srtInstant));
            mxModify.setItem("endTime", Date.from(edInstant));

            String cycleLabel = d.get("cycleLabel").toString();
            String dw = getDw(cycleLabel);
            String ms;
            if (Integer.parseInt(cycleLabel) < 7){
                 ms = "每" + d.get("cycleValue") + dw;
            }else {
                 ms = dw;
            }


            mxModify.setItem("cycleNote", ms);
            mxModify.setItem("luStandId", d.get("luStandId"));
            mxModify.setItem("devClass", d.get("devClass"));
            mxModify.setItem("devSpec", d.get("devSpec"));
            mxModify.setItem("luMech", d.get("luMech"));
            mxModify.setItem("luItem", d.get("luItem"));
            mxModify.setItem("luFatName", d.get("luFatName"));
            mxModify.setItem("luMode", d.get("luMode"));
            mxModify.setItem("cycleType", d.get("cycleType"));
            mxModify.setItem("cycleLabel", d.get("cycleLabel"));
            mxModify.setItem("cycleValue", d.get("cycleValue"));
            mxModify.setItem("note", d.get("note"));

            modify.addChildChangeSet("RwMx", mxModify);
        }
        return modify;
    }

    private String creatTaskScheduler(HashMap<String, String> devMap, List<HashMap<String, Object>> data) {
        String taskId = UUID.randomUUID().toString();

        LocalDateTime now = LocalDateTime.now();
        HashMap<String, Object> taskMap = new HashMap<>();
        taskMap.put("ID", taskId);
        taskMap.put("BILLSTATUS", "0");
        taskMap.put("TASKNAME", devMap.get("sbmc") + "的润滑计划");
        taskMap.put("UPDATER_CREATEDBY", now);
        taskMap.put("UPDATER_LASTCHANGEDBY", now);
        taskMap.put("UPDATER_CREATEDON", now);
        taskMap.put("UPDATER_LASTCHANGEDON", now);
        taskMap.put("VERSION", now);

        taskMap.put("sbid", devMap.get("sbid"));
        taskMap.put("sbbh", devMap.get("sbbh"));
        taskMap.put("sbbh_old", devMap.get("sbbh_old"));
        taskMap.put("sbmc", devMap.get("sbmc"));
        taskMap.put("sbld_lbbh", devMap.get("sbld_lbbh"));
        taskMap.put("sbld_lbmc", devMap.get("sbld_lbmc"));
        taskMap.put("bm_id", devMap.get("bm_id"));
        taskMap.put("bm_bh", devMap.get("bm_bh"));
        taskMap.put("bm_mc", devMap.get("bm_mc"));
        taskMap.put("shop_id", devMap.get("shop_id"));
        taskMap.put("shop_code", devMap.get("shop_code"));
        taskMap.put("shop_name", devMap.get("shop_name"));
        taskMap.put("zt_id", devMap.get("zt_id"));
        taskMap.put("zt_ztmc", devMap.get("zt_ztmc"));
        taskMap.put("abc_id", devMap.get("abc_id"));
        taskMap.put("abc_mc", devMap.get("abc_mc"));
        taskMap.put("ggxh", devMap.get("ggxh"));
        taskMap.put("xh", devMap.get("xh"));
        taskMap.put("bzxx", devMap.get("bzxx"));

        String creatTaskSQL = SqlUtil.getSql("SBSS_SBRH_TASK", taskMap);
        bqlExecuter.executeBqlStatement(creatTaskSQL, new ArrayList<>());

        data.forEach(d -> {
            String mxId = UUID.randomUUID().toString();
            String startTimeStr = d.get("startTime").toString();
            String endTimeStr = d.get("endTime").toString();
            String cycleLabel = d.get("cycleLabel").toString();
            String dw = getDw(cycleLabel);
            String ms;
            if (Integer.parseInt(cycleLabel) < 7){
                ms = "每" + d.get("cycleValue") + dw;
            }else {
                ms = dw;
            }

            HashMap<String, Object> taskMxData = new HashMap<>();
            taskMxData.put("ID", mxId);
            taskMxData.put("PARENTID", taskId);
            taskMxData.put("cycleNote", ms);
            taskMxData.put("STARTTIME", LocalDateTime.parse(startTimeStr, timeUtil.dateTimeFormatter));
            taskMxData.put("ENDTIME", LocalDateTime.parse(endTimeStr, timeUtil.dateTimeFormatter));

            taskMxData.put("luStandId", d.get("luStandId"));
            taskMxData.put("devClass", d.get("devClass"));
            taskMxData.put("devSpec", d.get("devSpec"));
            taskMxData.put("luMech", d.get("luMech"));
            taskMxData.put("luItem", d.get("luItem"));
            taskMxData.put("luFatName", d.get("luFatName"));
            taskMxData.put("luMode", d.get("luMode"));
            taskMxData.put("cycleType", d.get("cycleType"));
            taskMxData.put("cycleLabel", d.get("cycleLabel"));
            taskMxData.put("cycleValue", d.get("cycleValue"));
            taskMxData.put("note", d.get("note"));

            String creatTaskMXSQL = SqlUtil.getSql("SBSS_SBRH_TASKMX", taskMxData);

            bqlExecuter.executeBqlStatement(creatTaskMXSQL, new ArrayList<>());
        });


        return taskId;
    }

    private String getDw(String cycleLabel) {
        switch (cycleLabel) {
            case "1":
                return "小时";
            case "2":
                return "天";
            case "3":
                return "周";
            case "4":
                return "月";
            case "5":
                return "季";
            case "6":
                return "年";
            case "7":
                return "随一级保养";
            default:
                return "随二级保养";
        }
    }

    private String getString(Object value) {
        return value == null ? "" : value.toString();
    }

    private HashMap<String, String> IEntityDataToMap(IEntityData data) {
        HashMap<String, String> map = new HashMap<>();

        map.put("sbid", data.getID());
        map.put("sbbh", getString(data.getValue("sbbh")));
        map.put("sbbh_old", getString(data.getValue("sbbh_old")));
        map.put("sbmc", getString(data.getValue("sbmc")));
        map.put("ggxh", getString(data.getValue("ggxh")));
        map.put("xh", getString(data.getValue("xh")));

        // 获取班组名称
        IValuesContainer czbm = (IValuesContainer) data.getValue("czbm");
        map.put("bzxx", getString(czbm.getValue("czbm_bzmc")));

        IValuesContainer sbldId = (IValuesContainer) data.getValue("sblb_id");
        map.put("sbld_lbbh", getString(sbldId.getValue("sblb_id_lbbh")));
        map.put("sbld_lbmc", getString(sbldId.getValue("sblb_id_lbmc")));

        IValuesContainer bmbhId = (IValuesContainer) data.getValue("bmbh_id");
        map.put("bm_id", getString(bmbhId.getValue("bmbh_id")));
        map.put("bm_bh", getString(bmbhId.getValue("bmbh_id_code")));
        map.put("bm_mc", getString(bmbhId.getValue("bmbh_id_name")));

        IValuesContainer shopId = (IValuesContainer) data.getValue("shop_id");
        map.put("shop_id", getString(shopId.getValue("shop_id")));
        map.put("shop_code", getString(shopId.getValue("shop_id_ShopCode")));
        map.put("shop_name", getString(shopId.getValue("shop_id_ShopName")));

        IValuesContainer zt = (IValuesContainer) data.getValue("zt");
        map.put("zt_id", getString(zt.getValue("zt")));
        map.put("zt_ztmc", getString(zt.getValue("zt_ztmc")));

        IValuesContainer abc = (IValuesContainer) data.getValue("abc");
        map.put("abc_id", getString(abc.getValue("abc")));
        map.put("abc_mc", getString(abc.getValue("abc_lxmc")));

        return map;
    }

    ;
}
